package bitmap

type Bitmap struct {
	max      int
	bits     []uint64
	dirty    bool
	openBits []int
}

func New(max int) *Bitmap {
	var l int
	l = max / 64
	if max%64 > 0 {
		l++
	}

	return &Bitmap{
		max:   max,
		bits:  make([]uint64, l, l),
		dirty: true,
	}
}

func (b *Bitmap) GetOpenBits() []int {
	if b.dirty {
		b.dirty = false
		b.openBits = b.openBits[:0]
		for i := 0; i < len(b.bits); i++ {
			v := b.bits[i]
			if v > 0 {
				for j := 0; j < 64; j++ {
					if v&(1<<j) > 0 {
						b.openBits = append(b.openBits, i*64+j)
					}
				}
			}
		}
	}
	return b.openBits
}

func (b *Bitmap) Set(i int) {
	if i < b.max {
		k := i / 64
		j := i % 64
		b.bits[k] = b.bits[k] | (1 << j)
		b.dirty = true
	}
}

func (b *Bitmap) Clear(i int) {
	if i < b.max {
		k := i / 64
		j := i % 64
		b.bits[k] = b.bits[k] & (0xFFFFFFFFFFFFFFFF ^ (1 << j))
		b.dirty = true
	}
}

func (b *Bitmap) Test(i int) bool {
	if i < b.max {
		k := i / 64
		j := i % 64
		return b.bits[k]&(1<<j) > 0

	} else {
		return false
	}
}
